package com.shiroDemo.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 自定义realm，使用jdbc的形式
 * Created by xiongjie on 2018/10/15.
 */
public class MyRealm extends AuthorizingRealm {

    private Map<String,String> userMap=new HashMap<String, String>(16);
    private Map<String,Set<String>> roleMap=new HashMap<String, Set<String>>(16);
    private Map<String,Set<String>> permissionMap=new HashMap<String, Set<String>>(16);

    {
        super.setName("MyRealm");
        //代码块初始化变量，这里模拟数据库
        userMap.put("mark",new Md5Hash("123456","mark").toString());

        Set<String> roleSet=new HashSet<String>();
        roleSet.add("admin");
        roleSet.add("user");
        roleMap.put("mark",roleSet);

        Set<String> permissionSet=new HashSet<String>();
        permissionSet.add("user:select");
        permissionMap.put("mark",permissionSet);
    }

    /**
     * 授权方法
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        //1.从主体传过来的认证信息中获取用户名
        String username= (String) principals.getPrimaryPrincipal();

        //2.通过用户名从数据库中获取凭证
        Set<String> roles=getRolesByUserName(username);

        //3.通过用户名获取权限【中间有角色表连接】
        Set<String> permissions=getPermissionByUserName(username);

        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);


        return simpleAuthorizationInfo;
    }

    /**
     * 模拟数据库查询获取用户的角色权限
     * @param username
     * @return
     */
    private Set<String> getPermissionByUserName(String username) {
        return permissionMap.get(username);
    }

    /**
     * 模拟数据库查询获取用户的角色信息
     * @param username
     * @return
     */
    private Set<String> getRolesByUserName(String username) {
        return roleMap.get(username);
    }

    /**
     * 认证方法
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        //1.从主体传过来的认证信息中获取用户名
        String username= (String) token.getPrincipal();

        //2.通过用户名从数据库中获取凭证
        String password=getPasswordByUserName(username);
        if(password==null){
            return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(username,password,"MyRealm");
        //验证结果时，将salt添加辅助验证
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("mark"));
        return simpleAuthenticationInfo;
    }

    /**
     * 模拟数据库查询凭证
     * @param username
     * @return
     */
    private String getPasswordByUserName(String username) {
        return userMap.get(username);
    }
}
